Latviešu

Atklājiet uzlabotus UI modeļus ar React Portaliem. Uzziniet, kā renderēt modālus, uzvednītes un paziņojumus ārpus komponentu koka, saglabājot React notikumu un konteksta sistēmu.

React Portals apgūšana: Komponentu renderēšana ārpus DOM hierarhijas

Mūsdaiu tīmekļa izstrādes plašajā vidē React ir devis iespēju neskaitāmiem izstrādātājiem visā pasaulē veidot dinamiskus un ļoti interaktīvus lietotāja interfeisus. Tā uz komponentiem balstītā arhitektūra vienkāršo sarežģītas UI struktūras, veicinot atkārtotu lietošanu un uzturēšanu. Tomēr pat ar React elegantu dizainu izstrādātāji ik pa laikam saskaras ar situācijām, kurās standarta komponentu renderēšanas pieeja – kurā komponenti renderē savu izvadi kā bērnus sava vecāka DOM elementā – rada ievērojamus ierobežojumus.

Apsveriet modālu dialogu, kas ir jāparāda virs visa cita satura, paziņojumu joslu, kas peld globāli, vai konteksta izvēlni, kurai jāiziet no pārpildīta vecāka konteinera robežām. Šādās situācijās tradicionālā pieeja komponentu renderēšanai tieši vecāka DOM hierarhijā var radīt problēmas ar stilizēšanu (piemēram, z-index konflikti), izkārtojuma problēmas un notikumu izplatīšanas sarežģītību. Tieši šeit React Portals kļūst par spēcīgu un neaizstājamu rīku React izstrādātāju rīkkopā.

Šis visaptverošais ceļvedis dziļi iedziļinās React Portal modelī, izpētot tā pamatkoncepcijas, praktiskos pielietojumus, uzlabotus apsvērumus un labāko praksi. Neatkarīgi no tā, vai esat pieredzējis React izstrādātājs vai tikai sākat savu ceļojumu, portālu izpratne atklās jaunas iespējas patiesi izturīgu un globāli pieejamu lietotāja pieredzi veidošanā.

Izprast galveno izaicinājumu: DOM hierarhijas ierobežojumi

React komponentes pēc noklusējuma renderē savu izvadi vecāka komponenta DOM mezglā. Tas rada tiešu kartējumu starp React komponentu koku un pārlūka DOM koku. Lai gan šī attiecība ir intuitīva un parasti labvēlīga, tā var kļūt par šķērsli, kad komponentes vizuālajai reprezentācijai ir jāatbrīvojas no tās vecāka ierobežojumiem.

Parastās situācijas un to sāpju punkti:

Katrā no šīm situācijām, cenšoties panākt vēlamo vizuālo rezultātu, izmantojot tikai standarta React renderēšanu, bieži vien rodas sarežģīts CSS, pārmērīgas `z-index` vērtības vai sarežģīta pozicionēšanas loģika, kuru ir grūti uzturēt un mērogot. Tieši šeit React Portals piedāvā tīru, idiātisku risinājumu.

Kas īsti ir React Portal?

React Portal nodrošina pirmklasīgu veidu, kā renderēt bērnus DOM mezglā, kas atrodas ārpus vecāka komponenta DOM hierarhijas. Neskatoties uz renderēšanu atsevišķā fiziskā DOM elementā, portāla saturs joprojām darbojas tā, it kā tas būtu tiešs bērns React komponentu kokā. Tas nozīmē, ka tas saglabā to pašu React kontekstu (piemēram, Context API vērtības) un piedalās React notikumu burbuļošanas sistēmā.

React Portālu kodols slēpjas `ReactDOM.createPortal()` metodē. Tās paraksts ir vienkāršs:

ReactDOM.createPortal(child, container)

Kad izmantojat `ReactDOM.createPortal()`, React izveido jaunu virtuālo DOM apakškoku zem norādītā `container` DOM mezgla. Tomēr šī jaunā apakškoka joprojām ir loģiski savienota ar komponenti, kas izveidoja portālu. Šis "loģiskais savienojums" ir galvenais, lai saprastu, kāpēc notikumu burbuļošana un konteksts darbojas, kā gaidīts.

Savas pirmās React portāla iestatīšana: vienkāršs modāls piemērs

Apskatīsim kopīgu lietošanas gadījumu: modāla dialoga izveidi. Lai ieviestu portālu, vispirms ir nepieciešams mērķa DOM elements jūsu `index.html` (vai kur atrodas jūsu lietojumprogrammas saknes HTML fails), kur tiks renderēts portāla saturs.

1. darbība: sagatavojiet mērķa DOM mezglu

Atveriet savu `public/index.html` failu (vai ekvivalentu) un pievienojiet jaunu `div` elementu. Parasti to pievieno tieši pirms aizverošās `body` tagas, ārpus jūsu galvenās React lietojumprogrammas saknes.


<body>
  <!-- Jūsu galvenā React lietotnes sakne -->
  <div id="root"></div>

  <!-- Šeit tiks renderēts mūsu portāla saturs -->
  <div id="modal-root"></div>
</body>

2. darbība: izveidojiet portāla komponentu

Tagad izveidosim vienkāršu modālu komponentu, kas izmanto portālu.


// Modal.js
import React, { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';

const modalRoot = document.getElementById('modal-root');

const Modal = ({ children, isOpen, onClose }) => {
  const el = useRef(document.createElement('div'));

  useEffect(() => {
    // Pievienojiet div modāla saknei, kad komponente tiek montēta
    modalRoot.appendChild(el.current);

    // Tīrīšana: noņemiet div, kad komponente tiek demontēta
    return () => {
      modalRoot.removeChild(el.current);
    };
  }, []); // Tukša atkarību masīvs nozīmē, ka tas darbojas vienreiz pie montāžas un vienreiz pie demontāžas

  if (!isOpen) {
    return null; // Neredziet neko, ja modāls nav atvērts
  }

  return ReactDOM.createPortal(
    <div style={{
      position: 'fixed',
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      backgroundColor: 'rgba(0, 0, 0, 0.5)',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      zIndex: 1000 // Nodrošiniet, lai tas būtu virspusē
    }}>
      <div style={{
        backgroundColor: 'white',
        padding: '20px',
        borderRadius: '8px',
        boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
        maxWidth: '500px',
        width: '90%'
      }}>
        {children}
        <button onClick={onClose} style={{ marginTop: '15px' }}>Aizvērt modālu</button>
      </div>
    </div>,
    el.current // Renderējiet modāla saturu mūsu izveidotajā div, kas atrodas modalRoot
  );
};

export default Modal;

Šajā piemērā mēs izveidojam jaunu `div` elementu katrai modālu instancei (`el.current`) un pievienojam to `modal-root`. Tas ļauj mums vajadzības gadījumā pārvaldīt vairākus modālus, neļaujot tiem traucēt cits citu dzīves ciklu vai saturu. Faktiskais modāla saturs (pārklājums un baltā kaste) pēc tam tiek renderēts šajā `el.current` izmantojot `ReactDOM.createPortal`.

3. darbība: izmantojiet modālu komponentu


// App.js
import React, { useState } from 'react';
import Modal from './Modal'; // Pieņemot, ka Modal.js atrodas tajā pašā direktorijā

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);

  const handleOpenModal = () => setIsModalOpen(true);
  const handleCloseModal = () => setIsModalOpen(false);

  return (
    <div style={{ padding: '20px' }}>
      <h1>React Portal piemērs</h1>
      <p>Šis saturs ir daļa no galvenās lietojumprogrammas koka.</p>
      <button onClick={handleOpenModal}>Atvērt globālo modālu</button>

      <Modal isOpen={isModalOpen} onClose={handleCloseModal}>
        <h3>Sveicieni no portāla!</h3>
        <p>Šis modāla saturs tiek renderēts ārpus 'root' div, bet joprojām tiek pārvaldīts ar React.</p>
      </Modal>
    </div>
  );
}

export default App;

Lai gan `Modal` komponente tiek renderēta `App` komponentes iekšienē (kas savukārt atrodas `root` div), tās faktiskā DOM izvade parādās `modal-root` div iekšpusē. Tas nodrošina, ka modāls pārklāj visu bez `z-index` vai `overflow` problēmām, vienlaikus joprojām gūstot labumu no React stāvokļa pārvaldības un komponentu dzīves cikla.

Galvenie lietošanas gadījumi un uzlaboti React Portāla lietojumi

Lai gan modāli ir klišejisks piemērs, React Portālu lietderība sniedzas daudz tālāk par vienkāršiem uznirsto logiem. Apskatīsim vairāk uzlabotu scenāriju, kur portāli piedāvā elegantus risinājumus.

1. Izturīgi modāli un dialogu sistēmas

Kā redzams, portāli vienkāršo modālu ieviešanu. Galvenās priekšrocības ietver:

2. Dinamiskas uzvednes, uznirstošie logi un izkrītošās izvēlnes

Līdzīgi modāliem, šiem elementiem bieži vien ir jāparādās blakus trigerējošajam elementam, bet arī jāizlaužas no ierobežotajiem vecāku izkārtojumiem.

3. Globāli paziņojumi un tosta ziņojumi

Lietojumprogrammām bieži ir nepieciešama sistēma nebloķējošu, īslaicīgu ziņojumu parādīšanai (piemēram, "Prece pievienota grozam!", "Tīkla savienojums zudis").

4. Pielāgotas konteksta izvēlnes

Kad lietotājs noklikšķina ar peles labo pogu uz elementa, bieži parādās konteksta izvēlne. Šai izvēlnei ir jābūt precīzi novietotai pie kursora atrašanās vietas un jāpārklāj viss pārējais saturs. Portāli šeit ir ideāli:

5. Integrācija ar trešās puses bibliotēkām vai ne-React DOM elementiem

Iedomājieties, ka jums ir esoša lietojumprogramma, kuras daļu UI pārvalda mantota JavaScript bibliotēka, vai varbūt pielāgotā karšu risinājumā, kas izmanto savus DOM mezglus. Ja vēlaties renderēt nelielu, interaktīvu React komponentu šādā ārējā DOM mezglā, `ReactDOM.createPortal` ir jūsu tilts.

Uzlaboti apsvērumi, izmantojot React Portālus

Lai gan portāli atrisina sarežģītas renderēšanas problēmas, ir ļoti svarīgi saprast, kā tie mijiedarbojas ar citām React funkcijām un DOM, lai tos efektīvi izmantotu un izvairītos no izplatītām kļūdām.

1. Notikumu burbuļošana: svarīga atšķirība

Viens no visspēcīgākajiem un bieži vien nepareizi saprastajiem React Portālu aspektiem ir to uzvedība attiecībā uz notikumu burbuļošanu. Neskatoties uz to, ka tie tiek renderēti pilnīgi citā DOM mezglā, notikumi, kas tiek izšauti no elementiem portāla iekšienē, joprojām burbuļos caur loģisko React komponentu koku tā, it kā portāla nebūtu. Tas ir tāpēc, ka React notikumu sistēma ir sintētiska un vairumā gadījumu darbojas neatkarīgi no dabiskās DOM notikumu burbuļošanas.

2. Context API un portāli

Context API ir React mehānisms vērtību kopīgošanai (piemēram, tēmas, lietotāja autentifikācijas statusu) visā komponentu kokā bez prop-drilling. Par laimi, Context darbojas nevainojami ar portāliem.

3. Pieejamība (A11y) ar portāliem

Pieejamu UI veidošana ir vissvarīgākā globālai auditorijai, un portāli ievieš īpašus A11y apsvērumus, īpaši modāliem un dialogiem.

4. Stilēšanas problēmas un risinājumi

Lai gan portāli atrisina DOM hierarhijas problēmas, tie neuzlabo visas stilēšanas sarežģītības.

5. Server-Side Rendering (SSR) apsvērumi

Ja jūsu lietojumprogramma izmanto Server-Side Rendering (SSR), jums jābūt uzmanīgam attiecībā uz to, kā portāli darbojas.

6. Komponentu testēšana, izmantojot portālus

Testēšana komponentēm, kas renderē caur portāliem, var būt nedaudz atšķirīga, taču tā ir labi atbalstīta ar populārām testēšanas bibliotēkām, piemēram, React Testing Library.

Izplatītas kļūdas un labākā prakse React Portāliem

Lai nodrošinātu, ka jūsu React Portālu lietojums ir efektīvs, uzturams un darbojas labi, apsveriet šīs labākās prakses un izvairieties no izplatītām kļūdām:

1. Nepārmērīgi izmantojiet portālus

Portāli ir spēcīgi, taču tie jāizmanto saprātīgi. Ja komponentes vizuālo izvadi var panākt, neizjaucot DOM hierarhiju (piemēram, izmantojot relatīvu vai absolūtu pozicionēšanu ne-pārplūstošā vecākā), tad dariet tā. Pārmērīga portālu paļaušanās dažkārt var sarežģīt DOM struktūras atkļūdošanu, ja tā netiek rūpīgi pārvaldīta.

2. Nodrošiniet pareizu tīrīšanu (demontāžu)

Ja dinamiski izveidojat DOM mezglu savam portālam (kā mūsu `Modal` piemērā ar `el.current`), pārliecinieties, ka to tīrāt, kad komponente, kas izmanto portālu, tiek demontēta. `useEffect` tīrīšanas funkcija ir ideāla tam, lai novērstu atmiņas noplūdes un nesakārtotu DOM ar atraitņiem elementiem.


useEffect(() => {
  // ... pievienojiet el.current
  return () => {
    // ... noņemiet el.current;
  };
}, []);

Ja vienmēr renderējat fiksētā, iepriekš pastāvošā DOM mezglā (piemēram, vienā `modal-root`), paša mezgla tīrīšana nav nepieciešama, taču nodrošinot, ka portāla saturs pareizi tiek demontēts, kad vecāka komponente tiek demontēta, joprojām automātiski pārvalda React.

3. Veiktspējas apsvērumi

Lielākajā daļā lietošanas gadījumu (modāli, uzvednes) portāliem ir niecīga ietekme uz veiktspēju. Tomēr, ja jūs renderējat ārkārtīgi lielu vai bieži atjauninātu komponentu caur portālu, apsveriet parastos React veiktspējas optimizācijas (piemēram, `React.memo`, `useCallback`, `useMemo`) tāpat kā jebkuru citu sarežģītu komponentu.

4. Vienmēr dodiet priekšroku pieejamībai

Kā izcelti, pieejamība ir kritiskāka. Nodrošiniet, lai jūsu portālā renderētais saturs atbilstu ARIA vadlīnijām un nodrošinātu nevainojamu pieredzi visiem lietotājiem, īpaši tiem, kas paļaujas uz tastatūras navigāciju vai ekrāna lasītājiem.

5. Izmantojiet semantisko HTML portālu iekšienē

Lai gan portāls ļauj vizuāli renderēt saturu jebkur, atcerieties izmantot semantiskus HTML elementus savā portāla bērniem. Piemēram, dialogam vajadzētu izmantot `

` elementu (ja tas tiek atbalstīts un stilizēts) vai `div` ar `role="dialog"` un atbilstošiem ARIA atribūtiem. Tas palīdz pieejamībai un SEO.

6. Kontekstualizējiet savu portāla loģiku

Sarežģītām lietojumprogrammām apsveriet iespēju iekapsulēt savu portāla loģiku atkārtoti lietojamā komponentē vai pielāgotā izgriezumā. Piemēram, `useModal` izgriezums vai vispārīgs `PortalWrapper` komponents var abstrahēt `ReactDOM.createPortal` zvanu un pārvaldīt DOM mezglu izveidi/tīrīšanu, padarot jūsu lietojumprogrammas kodu tīrāku un modulārāku.


// Vienkārša PortalWrapper piemērs
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';

const createWrapperAndAppendToBody = (wrapperId) => {
  const wrapperElement = document.createElement('div');
  wrapperElement.setAttribute('id', wrapperId);
  document.body.appendChild(wrapperElement);
  return wrapperElement;
};

const PortalWrapper = ({ children, wrapperId = 'portal-wrapper' }) => {
  const [wrapperElement, setWrapperElement] = useState(null);

  useEffect(() => {
    let element = document.getElementById(wrapperId);
    let systemCreated = false;
    // ja elements ar wrapperId neeksistē, izveidojiet un pievienojiet to body
    if (!element) {
      systemCreated = true;
      element = createWrapperAndAppendToBody(wrapperId);
    }
    setWrapperElement(element);

    return () => {
      // Izdzēšiet programmatiski izveidoto elementu
      if (systemCreated && element.parentNode) {
        element.parentNode.removeChild(element);
      }
    };
  }, [wrapperId]);

  if (!wrapperElement) return null;

  return ReactDOM.createPortal(children, wrapperElement);
};

export default PortalWrapper;

Šis `PortalWrapper` ļauj vienkārši iesaiņot jebkuru saturu, un tas tiks renderēts dinamiskā (un iztīrītā) DOM mezglā ar norādīto ID, vienkāršojot lietošanu visā jūsu lietotnē.

Secinājums: Globālās UI izstrādes pilnvarošana ar React Portāliem

React Portāli ir eleganta un būtiska funkcija, kas dod iespēju izstrādātājiem atbrīvoties no tradicionālajiem DOM hierarhijas ierobežojumiem. Tie nodrošina izturīgu mehānismu sarežģītu, interaktīvu UI elementu, piemēram, modālu, uzvedņu, paziņojumu un konteksta izvēlņu, veidošanai, nodrošinot, ka tie darbojas pareizi gan vizuāli, gan funkcionāli.

Izprotot, kā portāli uztur loģisko React komponentu koku, nodrošinot nevainojamu notikumu burbuļošanu un konteksta plūsmu, izstrādātāji var radīt patiesi izsmalcinātus un pieejamus lietotāja interfeisus, kas atbilst dažādām globālām auditorijām. Neatkarīgi no tā, vai veidojat vienkāršu tīmekļa vietni vai sarežģītu uzņēmuma lietojumprogrammu, React Portālu apgūšana ievērojami uzlabos jūsu spēju izveidot elastīgas, veiktspējīgas un patīkamas lietotāja pieredzes. Pieņemiet šo jaudīgo modeli un atbloķējiet nākamo React izstrādes līmeni!